using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace LogFileViewer
{
    public partial class MainWindow : Form
    {

        /// <summary>
        ///     This method is used when a logfile is loaded for the first time.
        /// 
        ///     (BETA TEST)
        /// </summary>
        /// <param name="filename"></param>
        private bool LoadLogfileNew(string filename)
        {
            FileOpenManager openMan = new FileOpenManager(this.data);
            this.dataAccess = openMan.OpenFileFirstTime(filename);

            // Iterator settings for active row reload operations
            if (sets.HandleReadMethod == (int)DataAccess.ReaderHandling.ActiveRows)
            {
                ProgressWindow progWin = new ProgressWindow(this.dataAccess);
                bool everythingOk = progWin.RunFileIndexer();

                if (everythingOk)
                {
                    // Set title of application with loaded file
                    this.Text = "LogFileViewer - " + filename;

                    // Update statusbar "All Entries"
                    UpdateAllEntriesInfoStatusbar();

                    // Updates the history menu
                    HistoryOrganizer(filename);
                }
                return everythingOk;
            }

            openMan.ReloadFileContents(this.dataAccess);
            this.data = openMan.Data;

            // Check if data exists in collection
            if (this.data != null)
            {
                bool containsData = false;
                foreach (List<LogEntry> list in this.data.Values)
                {
                    if (list.Count > 0)
                    {
                        containsData = true;
                        break;
                    }
                }

                if (containsData)
                {
                    // Set title of application with loaded file
                    this.Text = "LogFileViewer - " + filename;

                    // Display log file entries in listview
                    PopulateListView();

                    // Update statusbar "All Entries"
                    UpdateAllEntriesInfoStatusbar();

                    // Updates the history menu
                    HistoryOrganizer(filename);
                    return true;
                }
                else
                {
                    MessageBox.Show("The log file cannot be opened, it contains no entries.", "Empty Logfile", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            return false;
        }


        private void ActivateType(MessageTypes type)
        {
            sets.SelectedTypes.Add(type.ToString());
            sets.Save();
            if (sets.HandleReadMethod == (int)DataAccess.ReaderHandling.ActiveTypes)
            {
                FileOpenManager manager = new FileOpenManager(this.data);
                manager.ReloadFileContents(this.dataAccess);
                this.data = manager.Data;
            }

            // Iterator settings for active row reload operations
            setListViewVirtualMode();
        }

        private void DeactivateType(MessageTypes type)
        {
            sets.SelectedTypes.Remove(type.ToString());
            if (sets.HandleReadMethod == (int)DataAccess.ReaderHandling.ActiveTypes)
            {
                cleanSingleType(type);
            }

            // Iterator settings for active row reload operations
            setListViewVirtualMode();
        }

        /// <summary>
        ///     Checks if virtual mode is required for list view
        ///     and fulfils several jobs in return.
        /// </summary>
        private void setListViewVirtualMode()
        {
            this.listView.Items.Clear();
            this.listView.VirtualMode = true;
            this.listView.VirtualListSize = this.dataAccess != null ? this.dataAccess.EveryLogEntriesAmountAll : 0;
        }

        private void resetListViewVirtualMode()
        {
            this.listView.VirtualListSize = 0;
            this.listView.VirtualMode = false;
        }

        private void listView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
        {
            e.Item = RetrieveNeededListViewItem(e.ItemIndex);
        }

        private ListViewItem RetrieveNeededListViewItem(int i)
        {
            LogEntry entry = RetrieveNeededEntry(i);
            if (entry != null)
            {
                // Create listview item from log entry
                ListViewItem item = Utilities.getListViewItem(entry);
                return item;
            }
            return null;
        }

        private LogEntry RetrieveNeededEntry(int i)
        {
            AccessReaderHandler readerHandler = new AccessReaderHandler(this.data, this.dataAccess);

            int indexInCurrent = i;
            MessageTypes type = MessageTypes.UNDEFINED;
            Dictionary<MessageTypes, long[]> indexes = this.dataAccess.LineIndexes;
            for (int j = 0; j < sets.SelectedTypes.Count; j++)
            {
                MessageTypes thisType = MessageType.GetMessageType(sets.SelectedTypes[j]);
                if (indexes.ContainsKey(thisType))
                {
                    if (indexes[thisType].Length <= indexInCurrent)
                    {
                        // Index is meant to be in any of the following lists
                        indexInCurrent = indexInCurrent - indexes[thisType].Length;
                    }
                    else
                    {
                        // Index is settled in current type list
                        type = thisType;
                        break;
                    }
                }

            }

            if (type == MessageTypes.UNDEFINED)
            {
                // Entry is not available
                Console.WriteLine("Cannot retrieve item <" + i + ">, type <" + type.ToString() + "> not in dictionary.");
                return null;
            }

            // Use information to get the right log entry
            long[] lineIndexes = indexes[type];
            LogEntry entry = null;
            if (lineIndexes != null)
            {
                long lineIndex = lineIndexes[indexInCurrent];
                entry = readerHandler.readEntry(type, lineIndex);
            }

            return entry;
        }
    }
}

